#!/usr/bin/perl

$xcodedir = $ARGV[0];
$plaf = lc $ARGV[1];

print "XCode dir: $xcodedir\n";
print "Plaf: $plaf\n";

if ($plaf !~ /^i(phone|pad|os)/) {
    print "Platform is not iOS, so not performing postprocessing.\n";
    exit 0;
}

$logfile = "/tmp/ios-postprocess-log-$$.txt";
open LOG, ">$logfile";
select LOG;

sub main {
    print "[ GOOGLE PLAY GAMES iOS EXPORT POST-PROCESS LOG FILE ]\n";
    print "PLEASE READ THIS FILE UNTIL THE END TO SEE IF THERE ARE ERRORS!\n\n";
    print "XCode project: $xcodedir\n";

    $gpgsparams = `cat "$xcodedir/Libraries/GPGSParams.h"`;
    if ($? != 0) {
        return "Failed to read GPGSParams.h";
    }
    
    $gpgsparams =~ /^AppId=(.*)$/m or do {
        print "*** ERROR: Could not find AppId= in GPGSParams.h\n";
	print "Did you complete the iOS setup in Unity (File | iOS setup)?\n";
	return "Could not find AppId= in GPGSParams.h. Missing setup step?";
    };
    $appid = $1;
    
    $gpgsparams =~ /^BundleId=(.*)$/m or do {
        print "*** ERROR: Could not find BundleId= in GPGSParams.h\n";
	print "Did you complete the iOS setup in Unity (File | iOS setup)?\n";
	return "Could not find BundleId= in GPGSParams.h. Missing setup step?";
    };
    $bundleid = $1;

    print "App ID: $appid\n";
    print "Bundle ID: $bundleid\n\n";
    print "Editing Info.plist.\n";
    
    $plist = `cat "$xcodedir/Info.plist"`;
    if ($? != 0) {
        return "Failed to read Info.plist.";
    }

    $skip_plist = 0;

    if ($plist =~ /<key>GPGApplicationID<\/key>/) {
        # Looks like the games tags are already there...
        # Are they right?
        $skip_plist = 1;
        print "This Info.plist already had Google Play Games definitions.\n";
        print "Checking if they are correct.\n";
        $right = 1;

        # check GPGApplicationID
        if ($plist =~ /<key>GPGApplicationID<\/key>\s*<string>(.*?)<\/string>/) {
            if ($1 ne $appid) {
                print "*** ERROR: Info.plist lists app ID as $1, correct is $appid\n";
                $right = 0;
            } else {
                print "App ID looks right ($1 = $appid).\n";
            }
        } else {
            print "*** ERROR: Failed to retrive app id from Info.plist.\n";
            $right = 0;
        }
        
        # Check CFBundleURLSchemes
        if ($plist =~ /<key>CFBundleURLSchemes<\/key>\s*<array>\s*<string>$bundleid<\/string>/) {
            print "CFBundleURLSchemes looks right (has $bundleid).\n";
        } else {
            print "*** ERROR: CFBundleURLSchemes doesn't seem to have $bundleid.\n";
            $right = 0;
        }

        # Check CFBundleURLName
        if ($plist =~ /<key>CFBundleURLName<\/key>\s*<string>$bundleid<\/string>/) {
            print "CFBundleURLName looks right (has $bundleid).\n";
        } else {
            print "*** ERROR: CFBundleURLName doesn't seem to have $bundleid.\n";
            $right = 0;
        }

        if (!$right) {
            print "***\n";
            print "*** FATAL ERROR\n";
            print "*** It looks like you are trying to reuse an existing xcode output\n";
            print "*** project that already had Google Play Games settings in it before.\n";
            print "*** These settings do not seem to match this game's settings, so\n";
            print "*** we cannot proceed. Please generate your game to a new xcode\n";
            print "*** folder.\n\n";
            return "Output folder has pre-existing incompatible Google Play Games data.";
        }
    }

    if (!$skip_plist) {
        print "Adding app ID and URL types to pinfo.\n";
        $plistadd = "
        <key>GPGApplicationID</key>
        <string>$appid</string>
        <key>CFBundleURLTypes</key>
        <array>
            <dict>
                <key>CFBundleURLSchemes</key>
                <array>
                    <string>$bundleid</string>
                </array>
                <key>CFBundleURLName</key>
                <string>$bundleid</string>
            </dict>
        </array>";
        $plist =~ s/(<\/dict>\s*<\/plist>)/$plistadd\n<\/dict>\n<\/plist>/s;
    } else {
        print "Not adding app ID and URL types because they are already there.\n";
    }

    print "Fixing CFBundleIdentifier.\n";
    $plist =~ s/(<key>CFBundleIdentifier<\/key>\s*<string>).*?</\1$bundleid</s;

    print "Writing out Info.plist.\n";
    open PLIST, ">$xcodedir/Info.plist";
    print PLIST $plist;
    close PLIST;
    print "Info.plist edited successfully and written.\n";

		# TODO: This is fragile. We should search for projects instead of assuming the name is Unity-iPhone
    print "Reading in Xcode project.\n";
    $xproj = `cat "$xcodedir/Unity-iPhone.xcodeproj/project.pbxproj"`;
    if ($? != 0) {
        return "Failed to read in pbxproj.";
    }
    print "Add our -fobjc-arc flags.\n";

    $xproj =~ s/(.*\{isa\s*=\s*PBXBuildFile.*GPGS\w*\.m.*)\}\;/\1settings = {COMPILER_FLAGS = "-fobjc-arc"; }; };/g;

    print "Writing out Xcode project.\n";
    open XPROJ, ">$xcodedir/Unity-iPhone.xcodeproj/project.pbxproj";
    print XPROJ $xproj;
    close XPROJ;
    print "Xcode project edited successfully and written.\n";

    print "Setup successful. Output project is $xcodedir.\n\n";
    print <<END


TO FINISH CONFIGURING THE EXPORTED XCODE PROJECT

1. Add these frameworks:

      AddressBook
      AssetsLibrary
      CoreData
      CoreLocation
      CoreMotion
      CoreText
      MediaPlayer
      QuartzCore
      Security
      SystemConfiguration
      libc++.dylib

2. Add the following bundles and frameworks from the Google Plus
   and the Google Play Games SDKs. These can be downloaded from
   https://developers.google.com/games/services.

      GoogleOpenSource.framework
      GooglePlus.bundle
      GooglePlus.framework
      GooglePlayGames.bundle
      GooglePlayGames.framework

3. Add the '-ObjC' linker flag. To do this, select the top-level project
   object, select the 'Unity-iPhone' build target, then go to the
   Build Settings tab. Search for Other Linker Flags and add
   the '-ObjC' flag to that list.

4. Go to your Target -> Build Phases -> Compile Sources, select all GPGS*.m
   files, and double-click them to add the "-fobjc-arc" flag. This will enable
   ARC for these specific files.

5. If you want to run the project in the simulator (as opposed to an
   actual device, read the notes in the APPENDIX below.


Your project is now ready to build and deploy!






-- APPENDIX: Running on the simulator. --
You only need to read this section if you intend to run your project
in the simulator, as opposed to an actual device.

By default, the exported Unity project does not support calling native C
functions on the simulator, but those are needed for the Google Play Games
integration. To enable support for them in the simulator, edit the
Libraries/RegisterMonoModules.cpp file.

You will notice there are two sections near the top of the file that
are delimited by #if !(TARGET_IPHONE_SIMULATOR) and #endif.

    extern \"C\" {
        ....
    #if !(TARGET_IPHONE_SIMULATOR)
        .. declarations .. (zone A)
    #endif
    }
    
    void RegisterMonoModules()
    {
        ...
    #if !(TARGET_IPHONE_SIMULATOR)
        ...function calls... (zone B)
    #endif
    }

To enable the simulator to make the necessary C function calls, you need to:

1. Find the line that declares the mono_dl_register_symbol() function in Zone A.
2. Move it to the outside of Zone A, right after the #endif (but still inside
   the extern \"C\" block)
3. Find ALL the calls to mono_dl_register_symbol() in Zone B.
4. Move them ALL outside Zone B, after the #endif (but still inside
   the RegisterMonoModules() function).

So the final structure should look like:

    extern \"C\" {
        ....
    #if !(TARGET_IPHONE_SIMULATOR)
        .. declarations .. (zone A)
    #endif
        void mono_dl_register_symbol(const char* name, void *addr);
    }
    
    void RegisterMonoModules()
    {
        ...
    #if !(TARGET_IPHONE_SIMULATOR)
        ...function calls... (zone B)
    #endif
        mono_dl_register_symbol(\"GPGSFooBar1\", (void*)&GPGSFooBar1);
        mono_dl_register_symbol(\"GPGSFooBar2\", (void*)&GPGSFooBar2);
        mono_dl_register_symbol(\"GPGSFooBar3\", (void*)&GPGSFooBar3);
        mono_dl_register_symbol(\"GPGSFooBar4\", (void*)&GPGSFooBar4);
        ....
    }
END
    ;
    return "";
}

$err = main();
if ($err) {
    print "*** FATAL ERROR: $err\n\n";
}
close LOG;
system "open $logfile"

